package org.act.BPEL2Automata.automata.module;

import java.util.LinkedList;

/**
 * <b>SimpleLogicalFormulaImp</b> extends <b>LogicalFormula</b>.
 * It is one of basic operands(as well as 1/true and 0/false).
 * It's a 3-tuple : start-state,message and end-state.
 * Specially,it also can be instantiated as a valid or invalid 
 * logical formula.
 * @author baoxiwu<bb@feijiao.info>,ACT,Beihang University
 * @version 0.9.0
 * @since 2010-04-10
 * 
 */
public class SimpleLogicalFormulaImp extends LogicalFormula{
	//types of logical formula:invalid, valid or non of them.
	public static final int NON_VALID_OR_INVALID_LOGICAL_FORMULA = -1;
	public static final int INVALID_LOGICAL_FORMULA = 0;
	public static final int VALID_LOGICAL_FORMULA = 1;
	
	//a flag to show whether it's a valid or invalid logical formula,
	//namely its value's 1 or 0 constantly.
	//Its default value is NON_VALID_OR_INVALID_LOGICAL_FORMULA.
	private int logicalFormulaType = SimpleLogicalFormulaImp.NON_VALID_OR_INVALID_LOGICAL_FORMULA;  
	
	private State start = null;
	private Message message = null;
	private State end = null;
	
	//value of this logical formula,1 or 0.
	private boolean value = false;
	
	//ONLY generate valid or invalid logical formula.
	public SimpleLogicalFormulaImp(State key,int logicalFormulaType){
		this.setKey(key);
		
		if(logicalFormulaType == SimpleLogicalFormulaImp.VALID_LOGICAL_FORMULA){
			this.logicalFormulaType = SimpleLogicalFormulaImp.VALID_LOGICAL_FORMULA;
		}
		else
		if(logicalFormulaType == SimpleLogicalFormulaImp.INVALID_LOGICAL_FORMULA){
			this.logicalFormulaType = SimpleLogicalFormulaImp.INVALID_LOGICAL_FORMULA;
		}
	}
	
	
	public SimpleLogicalFormulaImp(State start,Message message,State end){
		this.setKey(start);
		
		this.start = start;
		this.message = message;
		this.end = end;
	}
	
	
	//setter and getter methods.
	public void setLogicalFormulaType(int type){
		this.logicalFormulaType = type;
	}
	
	public int getLogicalFormulaType(){
		return this.logicalFormulaType;
	}
	
	public void setStartState(State start){
		this.start = start;
	}
	
	public State getStartState(){
		return this.start;
	}
	
	public void setMessage(Message message){
		this.message = message;
	}
	
	public Message getMessage(){
		return this.message;
	}
	
	public void SetEndState(State end){
		this.end = end;
	}
	
	public State getEndState(){
		return this.end;
	}
	
	public void setValue(boolean value){
		this.value = value;
	}
	
	public boolean getValue(){
		return this.value;
	}
	
	/*
	 * TODO TESTING WANTED.
	 * this method returns the boolean value of this logical formula.
	 * And it needs to be implemented.
	 * 
	 * @return true if it's a valid logical formula,and false as a invalid logical
	 * formula
	 */
	public boolean calculate(){
		if(this.getLogicalFormulaType() ==  SimpleLogicalFormulaImp.INVALID_LOGICAL_FORMULA){
			return false;
		}
		else
		if(this.getLogicalFormulaType() ==  SimpleLogicalFormulaImp.VALID_LOGICAL_FORMULA){
			return true;
		}
		else{
			return this.value;
		}
	}
	
	
	public void update(State state,State newState){
		//for NON_VALID_OR_INVALID_LOGICAL_FORMULA
		if(this.getStartState() == state){
			this.setKey(newState);
			this.setStartState(newState);
			
			return;
		}
		
		//for valid or invalid simple logical formula
		//ONLY set key.
		if(this.getKey() == state){
			this.setKey(newState);
		}
	}
	
	
	//clone a copy and update it.
	public SimpleLogicalFormulaImp updateACopy(State newState){
		SimpleLogicalFormulaImp slf = new SimpleLogicalFormulaImp(newState,this.getMessage(),this.getEndState());
		
		return slf;
	}
	
	
	public SimpleLogicalFormulaImp updateACopy(LinkedList<State> stateSet,DualState newState,int matchType){
		//if THIS is a 1 or 0.NO replacement needed.
		if(this.getLogicalFormulaType() != SimpleLogicalFormulaImp.NON_VALID_OR_INVALID_LOGICAL_FORMULA){
			SimpleLogicalFormulaImp slf = new SimpleLogicalFormulaImp(newState,this.getLogicalFormulaType());
			return slf;
		}
		
		DualState state = null;
		

		if(matchType == LogicalFormula.MATCH_TYPE_LEFT){
			//search the DualState set to get one existed DualState with stateX and stateY.
			for(int i = 0; i < stateSet.size(); i++){
				if(((DualState)stateSet.get(i)).getStateX() == this.getEndState() && 
						((DualState)stateSet.get(i)).getStateY() == newState.getStateY()){
					state = (DualState)stateSet.get(i);
				}
			}
		}
		else{
			for(int i = 0; i < stateSet.size(); i++){
				if(((DualState)stateSet.get(i)).getStateX() == newState.getStateX() && 
						((DualState)stateSet.get(i)).getStateY() == this.getEndState()){
					state = (DualState)stateSet.get(i);
				}
			}
		}
		
		//new a SimpleLogicalFormulaImp object.
		SimpleLogicalFormulaImp slf = new SimpleLogicalFormulaImp(newState,this.getMessage(),state);
		
		return slf;
	}
	
	
	public String toString(){
		String result = "";
		
		if(this.getLogicalFormulaType() == SimpleLogicalFormulaImp.NON_VALID_OR_INVALID_LOGICAL_FORMULA){
			if(this.getMessage() != null && this.getEndState() != null){
				result += ("\tL(s" + this.getKey().getID() + ") = s" + this.getStartState().getID() + 
						"_mes" + this.getMessage().getID() + "->s" + this.getEndState().getID() + "\n");
			}
		}
		else{
			result += ("\tL(s" + this.getKey().getID() + ") = " + this.getLogicalFormulaType() + "\n");
		}
		
		return result;
	}
}
